home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH24 / FSPXW.ASM < prev    next >
Encoding:
Assembly Source File  |  1994-07-28  |  19.0 KB  |  899 lines

  1.         .286
  2.         page    58, 132
  3.         name    FSPXW
  4.         title    FSPXW (Flightstick Pro driver for XWING).
  5.         subttl    Copyright (C) 1994 Randall Hyde.
  6.  
  7.  
  8. ; FSPXW.EXE
  9. ;
  10. ;    Usage:
  11. ;        FSPXW
  12. ;
  13. ; This program executes the XWING.EXE program and patches it to use the
  14. ; Flightstick Pro.
  15.  
  16.  
  17. byp        textequ    <byte ptr>
  18. wp        textequ    <word ptr>
  19.  
  20.  
  21. cseg        segment para public 'CODE'
  22. cseg        ends
  23.  
  24. sseg        segment    para stack 'STACK'
  25. sseg        ends
  26.  
  27. zzzzzzseg    segment    para public 'zzzzzzseg'
  28. zzzzzzseg    ends
  29.  
  30.         include        stdlib.a
  31.         includelib    stdlib.lib
  32.         matchfuncs
  33.  
  34.         ifndef    debug
  35. Installation    segment    para public 'Install'
  36. Installation    ends
  37.         endif
  38.  
  39. CSEG        segment    para public 'CODE'
  40.         assume    cs:cseg, ds:nothing
  41.  
  42. ; Timer interrupt vector
  43.  
  44. Int1CVect    dd    ?
  45.  
  46.  
  47. ; PSP-    Program Segment Prefix.  Needed to free up memory before running
  48. ;    the real application program.
  49.  
  50. PSP        dw    0
  51.  
  52.  
  53.  
  54. ; Program Loading data structures (for DOS).
  55.  
  56. ExecStruct    dw    0            ;Use parent's Environment blk.
  57.         dd    CmdLine            ;For the cmd ln parms.
  58.         dd    DfltFCB
  59.         dd    DfltFCB
  60. LoadSSSP    dd    ?
  61. LoadCSIP    dd    ?
  62. PgmName        dd    Pgm
  63.  
  64.  
  65. ; Variables for the throttle pot.
  66. ; LastThrottle contains the character last sent (so we only send one copy).
  67. ; ThrtlCntDn counts the number of times the throttle routine gets called.
  68.  
  69. LastThrottle    db    0
  70. ThrtlCntDn    db    10
  71.  
  72.  
  73. ; Button Mask- Used to mask out the programmed buttons when the game
  74. ; reads the real buttons.
  75.  
  76. ButtonMask    db    0f0h
  77.  
  78.  
  79. ; The following variables allow the user to reprogram the buttons.
  80.  
  81. KeyRdf        struct
  82. Ptrs        dw    ?
  83. ptr2        dw    ?
  84. ptr3        dw    ?
  85. ptr4        dw    ?
  86. Index        dw    ?
  87. Cnt        dw    ?
  88. Pgmd        dw    ?
  89. KeyRdf        ends
  90.  
  91.  
  92. ; Left codes are output if the cooley switch is pressed to the left.
  93.  
  94. Left        KeyRdf    <Left1, Left2, Left3, Left4, 0, 6, 1>
  95. Left1        dw    '7', 0,0,0,0,0,0,0,0
  96. Left2        dw    '4', 0,0,0,0,0,0,0,0
  97. Left3        dw    '1', 0,0,0,0,0,0,0,0
  98. Left4        dw    0,   0,0,0,0,0,0,0,0
  99.  
  100. ; Right codes are output if the cooley switch is pressed to the Right.
  101.  
  102. Right        KeyRdf    <Right1, Right2, Right3, Right4, 0, 6, 1>
  103. Right1        dw    '9', 0,0,0,0,0,0,0,0
  104. Right2        dw    '6', 0,0,0,0,0,0,0,0
  105. Right3        dw    '3', 0,0,0,0,0,0,0,0
  106. Right4        dw    0,   0,0,0,0,0,0,0,0
  107.  
  108. ; Up codes are output if the cooley switch is pressed Up.
  109.  
  110. Up        KeyRdf    <Up1, Up2, Up3, Up4, 0, 2, 1>
  111. Up1        dw    '8', 0,0,0,0,0,0,0,0
  112. Up2        dw    0,  0,0,0,0,0,0,0,0
  113. Up3        dw    0,  0,0,0,0,0,0,0,0
  114. Up4        dw    0,  0,0,0,0,0,0,0,0
  115.  
  116. ; DownKey codes are output if the cooley switch is pressed Down.
  117.  
  118. Down        KeyRdf    <Down1, Down2, Down3, Down4, 0, 2, 1>
  119. Down1        dw    '2', 0,0,0,0,0,0,0,0
  120. Down2        dw    0,   0,0,0,0,0,0,0,0
  121. Down3        dw    0,   0,0,0,0,0,0,0,0
  122. Down4        dw    0,   0,0,0,0,0,0,0,0
  123.  
  124. ; Sw0 codes are output if the user pulls the trigger.
  125.  
  126. Sw0        KeyRdf    <Sw01, Sw02, Sw03, Sw04, 0, 0, 0>
  127. Sw01        dw    0, 0,0,0,0,0,0,0,0
  128. Sw02        dw    0, 0,0,0,0,0,0,0,0
  129. Sw03        dw    0, 0,0,0,0,0,0,0,0
  130. Sw04        dw    0, 0,0,0,0,0,0,0,0
  131.  
  132.  
  133. ; Sw1 codes are output if the user presses Sw1 (the left button
  134. ; if the user hasn't swapped the left and right buttons).
  135.  
  136. Sw1        KeyRdf    <Sw11, Sw12, Sw13, Sw14, 0, 0, 0>
  137. Sw11        dw    0, 0,0,0,0,0,0,0,0
  138. Sw12        dw    0, 0,0,0,0,0,0,0,0
  139. Sw13        dw    0, 0,0,0,0,0,0,0,0
  140. Sw14        dw    0, 0,0,0,0,0,0,0,0
  141.  
  142. ; Sw2 codes are output if the user presses Sw2 (the middle button).
  143.  
  144. Sw2        KeyRdf    <Sw21, Sw22, Sw23, Sw24, 0, 2, 1>
  145. Sw21        dw    'w', 0,0,0,0,0,0,0,0
  146. Sw22        dw    0,   0,0,0,0,0,0,0,0
  147. Sw23        dw    0,   0,0,0,0,0,0,0,0
  148. Sw24        dw    0,   0,0,0,0,0,0,0,0
  149.  
  150. ; Sw3 codes are output if the user presses Sw3 (the right button
  151. ; if the user hasn't swapped the left and right buttons).
  152.  
  153. Sw3        KeyRdf    <Sw31, Sw32, Sw33, Sw34, 0, 0, 0>
  154. Sw31        dw    0, 0,0,0,0,0,0,0,0
  155. Sw32        dw    0, 0,0,0,0,0,0,0,0
  156. Sw33        dw    0, 0,0,0,0,0,0,0,0
  157. Sw34        dw    0, 0,0,0,0,0,0,0,0
  158.  
  159. ; Switch status buttons:
  160.  
  161. CurSw        db    0
  162. LastSw        db    0
  163.  
  164.  
  165. ;****************************************************************************
  166. ; FSPXW patch begins here.  This is the memory resident part.  Only put code
  167. ; which which has to be present at run-time or needs to be resident after
  168. ; freeing up memory.
  169. ;****************************************************************************
  170.  
  171. Main        proc
  172.         mov    cs:PSP, ds
  173.         mov    ax, cseg        ;Get ptr to vars segment
  174.         mov    ds, ax
  175.  
  176.  
  177. ; Get the current INT 1Ch interrupt vector:
  178.  
  179.         mov    ax, 351ch
  180.         int    21h
  181.         mov    wp Int1CVect, bx
  182.         mov    wp Int1CVect+2, es
  183.  
  184. ; The following call to MEMINIT assumes no error occurs.  If it does,
  185. ; we're hosed anyway.
  186.  
  187.         mov    ax, zzzzzzseg
  188.         mov    es, ax
  189.         mov    cx, 1024/16
  190.         meminit2
  191.  
  192.  
  193. ; Do some initialization before running the game.  These are calls to the
  194. ; initialization code which gets dumped before actually running XWING.
  195.  
  196.         call    far ptr ChkBIOS15
  197.         call    far ptr Identify
  198. ;        call    far ptr Reprogram
  199.         call    far ptr Calibrate
  200.  
  201. ; If any switches were programmed, remove those switches from the
  202. ; ButtonMask:
  203.  
  204.         mov    al, 0f0h        ;Assume all buttons are okay.
  205.         cmp    sw0.pgmd, 0
  206.         je    Sw0NotPgmd
  207.         and    al, 0e0h        ;Remove sw0 from contention.
  208. Sw0NotPgmd:
  209.  
  210.         cmp    sw1.pgmd, 0
  211.         je    Sw1NotPgmd
  212.         and    al, 0d0h        ;Remove Sw1 from contention.
  213. Sw1NotPgmd:
  214.  
  215.         cmp    sw2.pgmd, 0
  216.         je    Sw2NotPgmd
  217.         and    al, 0b0h        ;Remove Sw2 from contention.
  218. Sw2NotPgmd:
  219.  
  220.         cmp    sw3.pgmd, 0
  221.         je    Sw3NotPgmd
  222.         and    al, 070h        ;Remove Sw3 from contention.
  223. Sw3NotPgmd:
  224.         mov    ButtonMask, al        ;Save result as button mask
  225.  
  226. ; Now, free up memory from ZZZZZZSEG on to make room for XWING.
  227. ; Note: Absolutely no calls to UCR Standard Library routines from
  228. ; this point forward! (ExitPgm is okay, it's just a macro which calls DOS.)
  229. ; Note that after the execution of this code, none of the code & data
  230. ; from zzzzzzseg on is valid.
  231.  
  232.         mov    bx, zzzzzzseg
  233.         sub    bx, PSP
  234.         inc    bx
  235.         mov    es, PSP
  236.         mov    ah, 4ah
  237.         int    21h
  238.         jnc    GoodRealloc
  239.         print
  240.         byte    "Memory allocation error."
  241.         byte    cr,lf,0
  242.         jmp    Quit
  243.  
  244. GoodRealloc:
  245.  
  246. ; Now load the XWING program into memory:
  247.  
  248.         mov    bx, seg ExecStruct
  249.         mov    es, bx
  250.         mov    bx, offset ExecStruct    ;Ptr to program record.
  251.         lds    dx, PgmName
  252.         mov    ax, 4b01h        ;Load, do not exec, pgm
  253.         int    21h
  254.         jc    Quit            ;If error loading file.
  255.  
  256. ; Search for the joystick code in memory:
  257.  
  258.         mov    si, zzzzzzseg
  259.         mov    ds, si
  260.         xor    si, si
  261.  
  262.         mov    di, cs
  263.         mov    es, di
  264.         mov    di, offset JoyStickCode
  265.         mov    cx, JoyLength
  266.         call    FindCode
  267.         jc    Quit            ;If didn't find joystick code.
  268.  
  269.  
  270. ; Patch the XWING joystick code here
  271.  
  272.         mov    byp ds:[si], 09ah    ;Far call
  273.         mov    wp ds:[si+1], offset ReadGame
  274.         mov    wp ds:[si+3], cs
  275.  
  276. ; Find the Button code here.
  277.  
  278.         mov    si, zzzzzzseg
  279.         mov    ds, si
  280.         xor    si, si
  281.  
  282.         mov    di, cs
  283.         mov    es, di
  284.         mov    di, offset ReadSwCode
  285.         mov    cx, ButtonLength
  286.         call    FindCode
  287.         jc    Quit
  288.  
  289. ; Patch the button code here.
  290.  
  291.         mov    byp ds:[si], 9ah
  292.         mov    wp ds:[si+1], offset ReadButtons
  293.         mov    wp ds:[si+3], cs
  294.         mov    byp ds:[si+5], 90h    ;NOP.
  295.  
  296.  
  297. ; Patch in our timer interrupt handler:
  298.  
  299.         mov    ax, 251ch
  300.         mov    dx, seg MyInt1C
  301.         mov    ds, dx
  302.         mov    dx, offset MyInt1C
  303.         int    21h
  304.  
  305.  
  306. ; Okay, start the XWING.EXE program running
  307.  
  308.         mov    ah, 62h            ;Get PSP
  309.         int    21h
  310.         mov    ds, bx
  311.         mov    es, bx
  312.         mov    wp ds:[10], offset Quit
  313.         mov    wp ds:[12], cs
  314.         mov    ss, wp cseg:LoadSSSP+2
  315.         mov    sp, wp cseg:LoadSSSP
  316.         jmp    dword ptr cseg:LoadCSIP
  317.  
  318.  
  319. Quit:        lds    dx, cs:Int1CVect        ;Restore timer vector.
  320.         mov    ax, 251ch
  321.         int    21h
  322.         ExitPgm
  323.  
  324. Main        endp
  325.  
  326. ;****************************************************************************
  327. ;
  328. ; ReadGame-    This routine gets called whenever XWing reads the joystick.
  329. ;        On every 10th call it will read the throttle pot and send
  330. ;        appropriate characters to the type ahead buffer, if
  331. ;        necessary.
  332.  
  333.         assume    ds:nothing
  334. ReadGame    proc    far
  335.         dec    cs:ThrtlCntDn        ;Only do this each 10th time
  336.         jne    SkipThrottle        ; XWING calls the joystick
  337.         mov    cs:ThrtlCntDn, 10    ; routine.
  338.  
  339.         push    ax
  340.         push    bx        ;No need to save bp, dx, or cx as
  341.         push    di        ; XWING preserves these.
  342.  
  343.         mov    ah, 84h
  344.         mov    dx, 103h    ;Read the throttle pot
  345.         int    15h
  346.  
  347. ; Convert the value returned by the pot routine into the four characters
  348. ; 0..63:"\", 64..127:"[", 128..191:"]", 192..255:<bs>, to denote zero, 1/3,
  349. ; 2/3, and full power, respectively.
  350.  
  351.         mov    dl, al
  352.         mov    ax, "\"        ;Zero power
  353.         cmp    dl, 192
  354.         jae    SetPower
  355.         mov    ax, "["        ;1/3 power.
  356.         cmp    dl, 128
  357.         jae    SetPower
  358.         mov    ax, "]"        ;2/3 power.
  359.         cmp    dl, 64
  360.         jae    SetPower
  361.         mov    ax, 8        ;BS, full power.
  362. SetPower:    cmp    al, cs:LastThrottle
  363.         je    SkipPIB
  364.         mov    cs:LastThrottle, al
  365.         call    PutInBuffer
  366.  
  367. SkipPIB:    pop    di
  368.         pop    bx
  369.         pop    ax
  370. SkipThrottle:    neg    bx        ;XWING returns data in these registers.
  371.         neg    di        ;We patched the NEG and STI instrs
  372.         sti            ; so do that here.
  373.         ret
  374. ReadGame    endp
  375.  
  376.         assume    ds:nothing
  377. ReadButtons    proc    far
  378.         mov    ah, 84h
  379.         mov    dx, 0
  380.         int    15h
  381.         not    al
  382.         and    al, ButtonMask        ;Turn off pgmd buttons.
  383.         ret
  384. ReadButtons    endp
  385.  
  386.  
  387.  
  388. ; MyInt1C- Called every 1/18th second.  Reads switches and decides if it
  389. ; should shove some characters into the type ahead buffer.
  390.  
  391.         assume    ds:cseg
  392. MyInt1c        proc    far
  393.         push    ds
  394.         push    ax
  395.         push    bx
  396.         push    dx
  397.         mov    ax, cseg
  398.         mov    ds, ax
  399.  
  400.         mov        al, CurSw
  401.         mov    LastSw, al
  402.  
  403.         mov    dx, 900h    ;Read the 8 switches.
  404.         mov    ah, 84h
  405.         int    15h
  406.  
  407.         mov    CurSw, al
  408.         xor    al, LastSw    ;See if any changes
  409.         jz    NoChanges
  410.         and    al, CurSw    ;See if sw just went down.
  411.         jz    NoChanges
  412.  
  413.  
  414. ; If a switch has just gone down, output an appropriate set of scan codes
  415. ; for it, if that key is active.  Note that pressing *any* key will reset
  416. ; all the other key indexes.
  417.  
  418.         test    al, 1        ;See if Sw0 (trigger) was pulled.
  419.         jz    NoSw0
  420.         cmp    Sw0.Pgmd, 0
  421.         je    NoChanges
  422.         mov    ax, 0
  423.         mov    Left.Index, ax    ;Reset the key indexes for all keys
  424.         mov    Right.Index, ax    ; except SW0.
  425.         mov    Up.Index, ax
  426.         mov    Down.Index, ax
  427.         mov    Sw1.Index, ax
  428.         mov    Sw2.Index, ax
  429.         mov    Sw3.Index, ax
  430.         mov    bx, Sw0.Index
  431.         mov    ax, Sw0.Index
  432.         mov    bx, Sw0.Ptrs[bx]
  433.         add    ax, 2
  434.         cmp    ax, Sw0.Cnt
  435.         jb    SetSw0
  436.         mov    ax, 0
  437. SetSw0:        mov    Sw0.Index, ax
  438.         call    PutStrInBuf
  439.         jmp    NoChanges
  440.  
  441.  
  442.  
  443. NoSw0:        test    al, 2        ;See if Sw1 (left sw) was pressed.
  444.         jz    NoSw1
  445.         cmp    Sw1.Pgmd, 0
  446.         je    NoChanges
  447.         mov    ax, 0
  448.         mov    Left.Index, ax    ;Reset the key indexes for all keys
  449.         mov    Right.Index, ax    ; except Sw1.
  450.         mov    Up.Index, ax
  451.         mov    Down.Index, ax
  452.         mov    Sw0.Index, ax
  453.         mov    Sw2.Index, ax
  454.         mov    Sw3.Index, ax
  455.         mov    bx, Sw1.Index
  456.         mov    ax, Sw1.Index
  457.         mov    bx, Sw1.Ptrs[bx]
  458.         add    ax, 2
  459.         cmp    ax, Sw1.Cnt
  460.         jb    SetSw1
  461.         mov    ax, 0
  462. SetSw1:        mov    Sw1.Index, ax
  463.         call    PutStrInBuf
  464.         jmp    NoChanges
  465.  
  466.  
  467. NoSw1:        test    al, 4        ;See if Sw2 (middle sw) was pressed.
  468.         jz    NoSw2
  469.         cmp    Sw2.Pgmd, 0
  470.         je    NoChanges
  471.         mov    ax, 0
  472.         mov    Left.Index, ax    ;Reset the key indexes for all keys
  473.         mov    Right.Index, ax    ; except Sw2.
  474.         mov    Up.Index, ax
  475.         mov    Down.Index, ax
  476.         mov    Sw0.Index, ax
  477.         mov    Sw1.Index, ax
  478.         mov    Sw3.Index, ax
  479.         mov    bx, Sw2.Index
  480.         mov    ax, Sw2.Index
  481.         mov    bx, Sw2.Ptrs[bx]
  482.         add    ax, 2
  483.         cmp    ax, Sw2.Cnt
  484.         jb    SetSw2
  485.         mov    ax, 0
  486. SetSw2:        mov    Sw2.Index, ax
  487.         call    PutStrInBuf
  488.         jmp    NoChanges
  489.  
  490.  
  491. NoSw2:        test    al, 8        ;See if Sw3 (right sw) was pressed.
  492.         jz    NoSw3
  493.         cmp    Sw3.Pgmd, 0
  494.         je    NoChanges
  495.         mov    ax, 0
  496.         mov    Left.Index, ax    ;Reset the key indexes for all keys
  497.         mov    Right.Index, ax    ; except Sw3.
  498.         mov    Up.Index, ax
  499.         mov    Down.Index, ax
  500.         mov    Sw0.Index, ax
  501.         mov    Sw1.Index, ax
  502.         mov    Sw2.Index, ax
  503.         mov    bx, Sw3.Index
  504.         mov    ax, Sw3.Index
  505.         mov    bx, Sw3.Ptrs[bx]
  506.         add    ax, 2
  507.         cmp    ax, Sw3.Cnt
  508.         jb    SetSw3
  509.         mov    ax, 0
  510. SetSw3:        mov    Sw3.Index, ax
  511.         call    PutStrInBuf
  512.         jmp    NoChanges
  513.  
  514.  
  515. NoSw3:        test    al, 10h        ;See if Cooly was pressed upwards.
  516.         jz    NoUp
  517.         cmp    Up.Pgmd, 0
  518.         je    NoChanges
  519.         mov    ax, 0
  520.         mov    Right.Index, ax    ;Reset all but Up.
  521.         mov    Left.Index, ax
  522.         mov    Down.Index, ax
  523.         mov    Sw0.Index, ax
  524.         mov    Sw1.Index, ax
  525.         mov    Sw2.Index, ax
  526.         mov    Sw3.Index, ax
  527.         mov    bx, Up.Index
  528.         mov    ax, Up.Index
  529.         mov    bx, Up.Ptrs[bx]
  530.         add    ax, 2
  531.         cmp    ax, Up.Cnt
  532.         jb    SetUp
  533.         mov    ax, 0
  534. SetUp:        mov    Up.Index, ax
  535.         call    PutStrInBuf
  536.         jmp    NoChanges
  537.  
  538.  
  539. NoUp:        test    al, 20h        ;See if Cooly was pressed to the left.
  540.         jz    NoLeft
  541.         cmp    Left.Pgmd, 0
  542.         je    NoChanges
  543.         mov    ax, 0
  544.         mov    Right.Index, ax    ;Reset all but Left.
  545.         mov    Up.Index, ax
  546.         mov    Down.Index, ax
  547.         mov    Sw0.Index, ax
  548.         mov    Sw1.Index, ax
  549.         mov    Sw2.Index, ax
  550.         mov    Sw3.Index, ax
  551.         mov    bx, Left.Index
  552.         mov    ax, Left.Index
  553.         mov    bx, Left.Ptrs[bx]
  554.         add    ax, 2
  555.         cmp    ax, Left.Cnt
  556.         jb    SetLeft
  557.         mov    ax, 0
  558. SetLeft:    mov    Left.Index, ax
  559.         call    PutStrInBuf
  560.         jmp    NoChanges
  561.  
  562.  
  563. NoLeft:        test    al, 40h        ;See if Cooly was pressed to Right
  564.         jz    NoRight
  565.         cmp    Right.Pgmd, 0
  566.         je    NoChanges
  567.         mov    ax, 0
  568.         mov    Left.Index, ax    ;Reset all but Right.
  569.         mov    Up.Index, ax
  570.         mov    Down.Index, ax
  571.         mov    Sw0.Index, ax
  572.         mov    Sw1.Index, ax
  573.         mov    Sw2.Index, ax
  574.         mov    Sw3.Index, ax
  575.         mov    bx, Right.Index
  576.         mov    ax, Right.Index
  577.         mov    bx, Right.Ptrs[bx]
  578.         add    ax, 2
  579.         cmp    ax, Right.Cnt
  580.         jb    SetRight
  581.         mov    ax, 0
  582. SetRight:    mov    Right.Index, ax
  583.         call    PutStrInBuf
  584.         jmp    NoChanges
  585.  
  586.  
  587. NoRight:    test    al, 80h        ;See if Cooly was pressed Downward.
  588.         jz    NoChanges
  589.         cmp    Down.Pgmd, 0
  590.         je    NoChanges
  591.         mov    ax, 0
  592.         mov    Left.Index, ax    ;Reset all but Down.
  593.         mov    Up.Index, ax
  594.         mov    Right.Index, ax
  595.         mov    Sw0.Index, ax
  596.         mov    Sw1.Index, ax
  597.         mov    Sw2.Index, ax
  598.         mov    Sw3.Index, ax
  599.         mov    bx, Down.Index
  600.         mov    ax, Down.Index
  601.         mov    bx, Down.Ptrs[bx]
  602.         add    ax, 2
  603.         cmp    ax, Down.Cnt
  604.         jb    SetDown
  605.         mov    ax, 0
  606. SetDown:    mov    Down.Index, ax
  607.         call    PutStrInBuf
  608.  
  609. NoChanges:    pop    dx
  610.         pop    bx
  611.         pop    ax
  612.         pop    ds
  613.         jmp    cs:Int1CVect
  614. MyInt1c        endp
  615.         assume    ds:nothing
  616.  
  617. ; PutStrInBuf-  BX points at a zero terminated string of words.
  618. ;        Output each word by calling PutInBuffer.
  619.  
  620. PutStrInBuf    proc    near
  621.         push    ax
  622.         push    bx
  623. PutLoop:    mov    ax, [bx]
  624.         test    ax, ax
  625.         jz    PutDone
  626.         call    PutInBuffer
  627.         add    bx, 2
  628.         jmp    PutLoop
  629.  
  630. PutDone:    pop    bx
  631.         pop    ax
  632.         ret
  633. PutStrInBuf    endp
  634.  
  635. ; PutInBuffer- Outputs character and scan code in AX to the type ahead
  636. ; buffer.
  637.  
  638.         assume    ds:nothing
  639. KbdHead        equ    word ptr ds:[1ah]
  640. KbdTail        equ    word ptr ds:[1ch]
  641. KbdBuffer    equ    word ptr ds:[1eh]
  642. EndKbd        equ    3eh
  643. Buffer        equ    1eh
  644.  
  645. PutInBuffer    proc    near
  646.         push    ds
  647.         push    bx
  648.         mov    bx, 40h
  649.         mov    ds, bx
  650.         pushf
  651.         cli                ;This is a critical region!
  652.         mov     bx, KbdTail             ;Get ptr to end of type
  653.         inc     bx                      ; ahead buffer and make room
  654.         inc     bx                      ; for this character.
  655.         cmp     bx, buffer+32           ;At physical end of buffer?
  656.         jb      NoWrap
  657.         mov     bx, buffer              ;Wrap back to 1eH if at end.
  658. ;
  659. NoWrap:         cmp     bx, KbdHead             ;Buffer overrun?
  660.         je      PIBDone
  661.         xchg    KbdTail, bx             ;Set new, get old, ptrs.
  662.         mov     ds:[bx], ax             ;Output AX to old location.
  663. PIBDone:    popf                ;Restore interrupts
  664.         pop    bx
  665.         pop    ds
  666.         ret
  667. PutInBuffer    endp
  668.  
  669.  
  670.  
  671. ;****************************************************************************
  672. ;
  673. ; FindCode: On entry, ES:DI points at some code in *this* program which
  674. ;        appears in the ATP game.  DS:SI points at a block of memory
  675. ;        in the ATP game.  FindCode searches through memory to find the
  676. ;        suspect piece of code and returns DS:SI pointing at the start of
  677. ;        that code.  This code assumes that it *will* find the code!
  678. ;        It returns the carry clear if it finds it, set if it doesn't.
  679.  
  680. FindCode    proc    near
  681.         push    ax
  682.         push    bx
  683.         push    dx
  684.  
  685. DoCmp:        mov    dx, 1000h
  686. CmpLoop:      push    di            ;Save ptr to compare code.
  687.         push    si            ;Save ptr to start of string.
  688.         push    cx            ;Save count.
  689.     repe    cmpsb
  690.         pop    cx
  691.         pop    si
  692.         pop    di
  693.         je    FoundCode
  694.         inc    si
  695.         dec    dx
  696.         jne    CmpLoop
  697.         sub    si, 1000h
  698.         mov    ax, ds
  699.         inc    ah
  700.         mov    ds, ax
  701.         cmp    ax, 9000h
  702.         jb    DoCmp
  703.  
  704.         pop    dx
  705.         pop    bx
  706.         pop    ax
  707.         stc
  708.         ret
  709.  
  710. FoundCode:    pop    dx
  711.         pop    bx
  712.         pop    ax
  713.         clc
  714.         ret
  715. FindCode    endp
  716.  
  717.  
  718. ;****************************************************************************
  719. ;
  720. ; Joystick and button routines which appear in application code.  This code is
  721. ; really data as the INT 21h patch code searches through memory for this code
  722. ; after loading a file from disk.
  723.  
  724.  
  725.  
  726. JoyStickCode    proc    near
  727.         sti
  728.         neg    bx
  729.         neg    di
  730.         pop    bp
  731.         pop    dx
  732.         pop    cx
  733.         ret
  734.         mov    bp, bx
  735.         in    al, dx
  736.         mov    bl, al
  737.         not    al
  738.         and    al, ah
  739.         jnz    $+11h
  740.         in    al, dx
  741. JoyStickCode    endp
  742. EndJSC:
  743.  
  744. JoyLength    =    EndJSC-JoyStickCode
  745.  
  746. ReadSwCode    proc
  747.         mov    dx, 201h
  748.         in    al, dx
  749.         xor    al, 0ffh
  750.         and    ax, 0f0h
  751. ReadSwCode    endp
  752. EndRSC:
  753.  
  754. ButtonLength    =    EndRSC-ReadSwCode
  755.  
  756. cseg        ends
  757.  
  758.  
  759. Installation    segment
  760.  
  761. ; Move these things here so they do not consume too much space in the
  762. ; resident part of the patch.
  763.  
  764. DfltFCB        db    3,"           ",0,0,0,0,0
  765. CmdLine        db    2, "  ", 0dh, 126 dup (" ")    ;Cmd line for program
  766. Pgm        db    "XWING.EXE",0
  767.         db    128 dup (?)            ;For user supplied name
  768.  
  769.  
  770. ; ChkBIOS15- Checks to see if the INT 15 driver for FSPro is present in memory.
  771.  
  772. ChkBIOS15    proc    far
  773.         mov    ah, 84h
  774.         mov    dx, 8100h
  775.         int    15h
  776.         mov    di, bx
  777.         strcmpl
  778.         db    "CH Products:Flightstick Pro",0
  779.         jne    NoDriverLoaded
  780.         ret
  781.  
  782. NoDriverLoaded:    print
  783.         byte    "CH Products SGDI driver for Flightstick Pro is not "
  784.         byte    "loaded into memory.",cr,lf
  785.         byte    "Please run FSPSGDI before running this program."
  786.         byte    cr,lf,0
  787.         exitpgm
  788.  
  789. ChkBIOS15    endp
  790.  
  791.  
  792. ;****************************************************************************
  793. ;
  794. ; Identify-    Prints a sign-on message.
  795.  
  796.         assume    ds:nothing
  797. Identify    proc    far
  798.  
  799. ; Print a welcome string.  Note that the string "VersionStr" will be
  800. ; modified by the "version.exe" program each time you assemble this code.
  801.  
  802.         print
  803.         db    cr,lf,lf
  804.         byte    "╓───────────────────────────────────────╖",cr,lf
  805.         byte    "║ X W I N G   P A T C H                 ║",cr,lf
  806.         byte    "║ CH Products Flightstick Pro           ║",cr,lf
  807.         byte    "║ Copyright 1993, 1994, Randall Hyde    ║",cr,lf
  808.         byte    "╙───────────────────────────────────────╜",cr,lf
  809.         db    lf
  810.         db    0
  811.  
  812.         ret
  813. Identify    endp
  814.  
  815. ;****************************************************************************
  816. ;
  817. ; Calibrate the throttle down here:
  818.  
  819.         assume    ds:nothing
  820. Calibrate    proc    far
  821.         print
  822.         byte    cr,lf,lf
  823.         byte    "Calibration:",cr,lf,lf
  824.         byte    "Move the throttle to one extreme and press any "
  825.         byte    "button:",0
  826.  
  827.         call    Wait4Button
  828.         mov    ah, 84h
  829.         mov    dx, 1h
  830.         int    15h
  831.         push    dx        ;Save pot 3 reading.
  832.  
  833.         print
  834.         byte    cr,lf
  835.         byte    "Move the throttle to the other extreme and press "
  836.         byte    "any button:",0
  837.  
  838.         call    Wait4Button
  839.         mov    ah, 84h
  840.         mov    dx, 1
  841.         int    15h
  842.         pop    bx
  843.         mov    ax, dx
  844.         cmp    ax, bx
  845.         jb    RangeOkay
  846.         xchg    ax, bx
  847. RangeOkay:    mov    cx, bx        ;Compute a centered value.
  848.         sub    cx, ax
  849.         shr    cx, 1
  850.         add    cx, ax
  851.         mov    ah, 84h
  852.         mov    dx, 303h    ;Calibrate pot three.
  853.         int    15h
  854.         ret
  855. Calibrate    endp
  856.  
  857.  
  858.  
  859. Wait4Button    proc    near
  860.         mov    ah, 84h        ;First, wait for all buttons
  861.         mov    dx, 0        ; to be released.
  862.         int    15h
  863.         and    al, 0F0h
  864.         cmp    al, 0F0h
  865.         jne    Wait4Button
  866.  
  867.         mov    cx, 0
  868. Delay:        loop    Delay
  869.  
  870. Wait4Press:    mov    ah, 1        ;Eat any characters from the
  871.         int    16h        ; keyboard which come along, and
  872.         je    NoKbd        ; handle ctrl-C as appropriate.
  873.         getc
  874.  
  875. NoKbd:        mov    ah, 84h        ;Now wait for any button to be
  876.         mov    dx, 0        ; pressed.
  877.         int    15h
  878.         and    al, 0F0h
  879.         cmp    al, 0F0h
  880.         je    Wait4Press
  881.  
  882.         ret
  883. Wait4Button    endp
  884.  
  885.  
  886.  
  887. Installation    ends
  888.  
  889. sseg        segment    para stack 'STACK'
  890.         dw    256 dup (0)
  891. endstk        dw    ?
  892. sseg        ends
  893.  
  894. zzzzzzseg    segment    para public 'zzzzzzseg'
  895. Heap        db    1024 dup (0)
  896. zzzzzzseg    ends
  897.  
  898.         end    Main
  899.